{==============================================================================|
| Project : MyPCSecurity                                        | C4-12-XX-XXX |
|==============================================================================|
| Content: Serial port support                                                 |
|==============================================================================|
| Copyright (c)2012-2012, Avalonweb - Mark Boyce                               |
|                                                                              |
|                                                                              |
|                                                                              |
|==============================================================================|
| Property of:                                                                 |
|                                                                              |
| Mark Boyce                                                                   |
| 43 Marlborough Rd                                                            |
| Bayswater                                                                    |
| Victoria                                                                     |
| Australia                                                                    |
| 3153                                                                         |
|                                                                              |
| Phone: *61(0)433268271                                                       |
| www.avalonweb.co.uk                                                          |
| sales@avalonweb.co.uk                                                        |
|                                                                              |
| All Rights Reserved.                                                         |
|==============================================================================}

unit com;

interface

uses
  SysUtils, Variants, Messages,Classes, Graphics, Forms,
  Dialogs, ZylSerialPort, common;

type
  T_SC = record
    got_start     : boolean;
    got_stop      : boolean;
    prev_char     : string;
end;

type
    TcomProtocol = class (TZylSerialPort)
    constructor Create(AOwner : TComponent);   reintroduce;
    destructor Destroy;  override;

  private
    serstring           : string;
    sc : T_SC;

    procedure cpOnReceive(Sender : TObject; Buffer : String);
    Procedure cpOnStatusEvent(sender : TObject; LineStatus : TLineStatusSet);

    procedure SerInitRcv;
  public
//    Procedure ToFile(Str : string);                     // Write a string to the debug file
    mComPort : TCommPort;
    function SerConnect : boolean;

  end;
var
  sInputStr: AnsiString;
  frmComProtocol : TComProtocol;

  implementation

uses main, DateUtils,
// FileIO, // For AppLog
windows;





{==============================================================================|
|   FormCreate                                                                 |
|   Function Type: Public                                                      |
|                                                                              |
|   TfrmComProtocol Class Constucter                                           |
|==============================================================================}
constructor TComProtocol.Create(AOwner : TComponent);
begin
  // Class Initialisation
  Inherited Create(AOwner);

  // Initialise Callbacks
  OnReceive             := cpOnReceive;
  OnLineStatusChange    := cpOnStatusEvent;

  SerInitRcv;         // Initialise Receive State Machine
end;

destructor TComProtocol.Destroy;
begin
  inherited;
end;



{==============================================================================|
|  Establishes connection using external call                                  |
|                                                                              }
function TComProtocol.SerConnect;
begin
  result := true;
//  if not sysCtrl.bHaveComPort then          // Only connect if you have a comport
//    exit;

  BaudRate                    := br019200;  // TBaudRate - baud rate value at which the communication device
                                            // operates

  CustomBaudRate              := 0;         // baud rate value at which the communication device operates,
                                            // when BaudRate property is set to brCustom

  DataWidth                   := dw8Bits;   // TDataWidth - number of bits in the bytes transmitted and
                                            // received

  Delay                       := 20;        // Word - Time interval between two receivings in milliseconds
  EnableDTROnOpen             := True;      // Boolean - enable / disable DTR when the port is open
  EnableRTSOnOpen             := True;      // Boolean - enable / disable RTS when the port is open
  HwFlowControl               := hfNONE;    // THwFlowControl - hardware flow control

  InputBuffer                 := 2048;      // Cardinal - recommended size of the device's internal input
                                            // buffer, in bytes

  OutputBuffer                := 2048;      // recommended size of the device's internal output buffer, in bytes
  Parity                      := pbNone;    // TParityBits - parity scheme to be used

  Port                        := mComPort;
                                            // TCommPort - serial port name. If you change the port, you need
                                            // to call the method Open again

  Priority                    := tpHighest; // TThreadPriority - priority of the reader thread
                              // tpHighest, tpNormal

  ReadIntervalTimeout         := 10;        // Longint - Maximum time allowed to elapse between the arrival
                                            // of two characters on the communications line, in milliseconds.
                                            // During a ReadFile operation, the time period begins when the
                                            // first character is received. If the interval between the
                                            // arrival of any two characters exceeds this amount,
                                            // the ReadFile operation is completed and any buffered data is
                                            // returned. A value of zero indicates that interval time-outs
                                            // are not used. A value of MAXDWORD, combined with zero values
                                            // for both the ReadTotalTimeoutConstant and
                                            // ReadTotalTimeoutMultiplier members, specifies that the read
                                            // operation is to return immediately with the characters that
                                            // have already been received, even if no characters have been
                                            // received.

  ReadTotalTimeoutConstant    := 1;         // Longint - Constant used to calculate the total time-out period
                                            // for read operations, in milliseconds. For each read operation,
                                            // this value is added to the product of the
                                            // ReadTotalTimeoutMultiplier member and the requested number of
                                            // bytes. A value of zero for both the ReadTotalTimeoutMultiplier
                                            // and ReadTotalTimeoutConstant members indicates that total
                                            // time-outs are not used for read operations

  ReadTotalTimeoutMultiplier  := 0;  // 10       // Longint - Multiplier used to calculate the total time-out
                                            // period for read operations, in milliseconds. For each read
                                            // operation, this value is multiplied by the requested number
                                            // of bytes to be read.

  StopBits                    := sb1Bit;    // TStopBits - number of stop bits to be used
  SwFlowControl               := sfNONE;    // TSwFlowControl - software flow control
  Tag                         := 0;         //
  WriteTotalTimeoutConstant   := 1;         // Longint - Constant used to calculate the total time-out period
                                            // for write operations, in milliseconds. For each write
                                            // operation, this value is added to the product of the
                                            // WriteTotalTimeoutMultiplier member and the number of bytes
                                            // to be written
  WriteTotalTimeoutMultiplier := 1;         // Longint - Multiplier used to calculate the total time-out
                                            // period for write operations, in milliseconds. For each write
                                            // operation, this value is multiplied by the number of bytes to
                                            // be written
  try
    open;                                   // Try to connect to Comport
  except
    result := false;
//    MessageDlg('Error opening Com Port ' + self.CommPortToString (mComPort) + ' as already in use.', mtWarning,[mbOk],0,mbOk);
//    io.AppLog('Comms disabled as Comport is in use');
  end;

  if (IsConnected <> mComPort) then //  returns the comm port connected to
  begin

    //memodbg.Text := 'Connected to Receiver' + CRLF;
    result := false;
    SerInitRcv;
  end;

end;




{==============================================================================}
{ Handle RS232 Comport Events.                                                 }
{ Reserverd for future expansion                                               }
procedure TComProtocol.cpOnStatusEvent(sender : TObject; LineStatus : TLineStatusSet);
begin
end;

///////////////////////////////
// Receive data from comm port

procedure TComProtocol.cpOnReceive(Sender : TObject; Buffer : String);
const

  STARTHI = #$98;
  STARTLO = #$E6;
  STOPHI = #$66;
  STOPLO = #$33;

var

  QtyBytes  : integer;
  c : string;
  idx  : integer;

begin

  QtyBytes := length(Buffer);

  for idx := 1 to QtyBytes do
  begin
    c := Buffer[idx];

    if (not sc.got_start) then
    begin
      if c = STARTLO then
      begin
        if sc.prev_char = STARTHI then
        begin
          sc.got_start := true;
          serstring := STARTHI;
        end;
      end;
    end // end got_start
    else
    begin
      if c = STOPLO then
      begin
        if sc.prev_char = STOPHI then
        begin
          sc.got_stop := true;
        end;
      end;
    end;

    serstring := serstring + c;
    sc.prev_char := c;

    if sc.got_stop then
    begin
      frmMain.winmsg.datastr      := serstring;
      frmMain.winmsg.destination  := MESS_PACKET;
      SendMessage( frmMain.Handle, WM_MESSAGE_MAINFORM, Integer(self),0);
      SerInitRcv;
    end;      // End Case
  end;// End Loop

end;



procedure TComProtocol.SerInitRcv;
begin
  sc.got_start    := false;
  sc.got_stop     := false;
  sc.prev_char    := '';
  serString       := '';
end;

end.
